package com.joker.demo.admin.router.impl;

import com.joker.demo.admin.router.ExecutorRouter;

import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 一致性哈希路由策略
 *
 * @author : feixiang.li
 * @since : 2025-07-29 17:29
 */
public class ConsistentHashExecutorRouter implements ExecutorRouter {

    // 虚拟节点数量
    private static final int VIRTUAL_NODES = 160;

    @Override
    public String route(String jobId, List<String> addressList) {
        if (addressList == null || addressList.isEmpty()) {
            return null;
        }

        if (addressList.size() == 1) {
            return addressList.get(0);
        }

        // 构建一致性哈希环
        SortedMap<Integer, String> hashRing = new TreeMap<>();
        for (String address : addressList) {
            for (int i = 0; i < VIRTUAL_NODES; i++) {
                String virtualNode = address + "&&VN" + i;
                int hash = hash(virtualNode);
                hashRing.put(hash, address);
            }
        }

        // 根据jobId计算哈希值
        int jobHash = hash(jobId);

        // 找到顺时针方向最近的节点
        SortedMap<Integer, String> tailMap = hashRing.tailMap(jobHash);
        int targetHash = tailMap.isEmpty() ? hashRing.firstKey() : tailMap.firstKey();

        return hashRing.get(targetHash);
    }

    /**
     * FNV哈希算法
     */
    private int hash(String key) {
        final int p = 16777619;
        int hash = (int) 2166136261L;
        for (int i = 0; i < key.length(); i++) {
            hash = (hash ^ key.charAt(i)) * p;
        }
        hash += hash << 13;
        hash ^= hash >> 7;
        hash += hash << 3;
        hash ^= hash >> 17;
        hash += hash << 5;
        return Math.abs(hash);
    }
} 